package com.uinnova.product.eam.web.cj;

import cn.hutool.core.lang.Assert;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.fastjson.JSONObject;
import com.binary.framework.util.ControllerUtils;
import com.binary.framework.web.RemoteResult;
import com.binary.jdbc.Page;
import com.uinnova.product.cj.feign.dto.PlanDesignInstanceDTO;
import com.uinnova.product.cj.feign.dto.PlanDesignShareRecordDTO;
import com.uinnova.product.cj.feign.dto.PlanVersionDTO;
import com.uinnova.product.eam.base.cj.ResultMsg;
import com.uinnova.product.eam.base.enums.ResultCodeEnum;
import com.uinnova.product.eam.feign.workable.FlowableFeign;
import com.uinnova.product.eam.model.cj.domain.PlanDesignInstance;
import com.uinnova.product.eam.model.cj.domain.PlanDesignShareRecord;
import com.uinnova.product.eam.model.cj.domain.TemplateType;
import com.uinnova.product.eam.model.cj.enums.PlanShareEnum;
import com.uinnova.product.eam.model.cj.enums.PlanSharePermissionEnum;
import com.uinnova.product.eam.model.cj.enums.PlanStatusEnum;
import com.uinnova.product.eam.model.cj.request.PlanDesignInstanceAddRequest;
import com.uinnova.product.eam.model.cj.request.PlanDesignInstanceQueryRequest;
import com.uinnova.product.eam.model.cj.request.PlanDesignInstanceUpdateRequest;
import com.uinnova.product.eam.model.cj.request.ProcessApprovalRequest;
import com.uinnova.product.eam.model.cj.vo.*;
import com.uinnova.product.eam.model.constants.Constants;
import com.uinnova.product.eam.service.cj.dao.PlanDesignInstanceDao;
import com.uinnova.product.eam.service.cj.service.PlanChapterInstanceService;
import com.uinnova.product.eam.service.cj.service.PlanDesignInstanceService;
import com.uinnova.product.eam.service.cj.service.ShareService;
import com.uinnova.product.eam.service.exception.BusinessException;
import com.uino.api.client.permission.IUserApiSvc;
import com.uino.bean.cmdb.base.LibType;
import com.uino.bean.permission.base.SysUser;
import com.uino.util.sys.SysUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.*;


/**
 * 方案设计 controller
 *
 * @author zhaoxin
 */
@RestController
@RequestMapping("/planDesign")
@Slf4j
public class PlanDesignInstanceController {

    @Resource
    private PlanDesignInstanceService planDesignInstanceService;

    @Resource
    private PlanChapterInstanceService planChapterInstanceService;

    @Resource
    private ShareService shareService;

    @Resource
    private PlanDesignInstanceDao planDesignInstanceDao;

    @Autowired
    private IUserApiSvc userApiSvc;

    /**
     * 方案设计新增
     */
    @PostMapping
    public ResultMsg addPlan(@RequestBody @Valid PlanDesignInstanceAddRequest request) {
        Long id = planDesignInstanceService.add(request);
        return new ResultMsg(id);
    }

    /**
     * 方案设计更新 修改
     */
    @PutMapping
    public ResultMsg updatePlan(@RequestBody @Valid PlanDesignInstanceUpdateRequest request) {
        Long result = planDesignInstanceService.update(request);
        if (Objects.equals(result, -1L)) {
            return new ResultMsg(false, ResultCodeEnum.APPROVE_ERROR.getCode(), "该方案已提交审批，请刷新后重试!");
        } else {
            return ResultMsg.ok();
        }
    }

    /**
     * 方案设计 重命名
     * 必填参数是：id、name
     */
    @PutMapping("rename")
    public ResultMsg rename(@RequestBody Map<String, Object> request) {
        planDesignInstanceService.rename(request);
        return ResultMsg.ok();
    }

    /**
     * 更新方案状态
     */
    @GetMapping("/updatePlanStatus")
    public ResultMsg updatePlanStatus(@RequestParam(name = "status", required = true) String status,
                                      @RequestParam(name = "planId") Long planId) {
        Set<String> sysIdSet = planDesignInstanceService.updatePlanStatus(status, planId);
        return new ResultMsg(sysIdSet);
    }

    /**
     * 根据id查询
     */
    @GetMapping("{id}")
    public ResultMsg findById(@PathVariable Long id, @RequestParam(defaultValue = "true") Boolean needAuth) {
        PlanDesignInstance plan = planDesignInstanceService.getPlanDesignInstance(id);
        log.info("(1)方案id:" + id +", 方案信息：" + JSONObject.toJSONString(plan));
        if (plan == null) {
            throw new BusinessException("方案已被删除!");
        }
        SysUser sysUser = SysUtil.getCurrentUserInfo();
        /**
         * 判断当前用户是否有 管理员菜单<架构设计清单> 菜单权限 (一般只有管理员有这个菜单权限)
         * 有此菜单权限的  都可以 查看/分享/协作 视图/方案
         * 菜单名称：架构设计清单  后续可能会更改 通过配置可配：admin.menu.name
         * @return
         */
        if (needAuth) {
            boolean isAdminRole = userApiSvc.isAdminRole();
            if (isAdminRole) {
                needAuth = false;
            }
        }
        if (!Objects.equals(plan.getCreatorCode(), sysUser.getLoginCode()) && Objects.equals(plan.getAssetsType(), Constants.DESIGN)
                && !plan.isProcessApproval() && needAuth) {
            PlanDesignShareRecord planDesignShareRecord = new PlanDesignShareRecord();
            planDesignShareRecord.setPlanDesignId(id);
            planDesignShareRecord.setSharedLoginCode(sysUser.getLoginCode());
            planDesignShareRecord.setStatus(PlanShareEnum.SHARING.getStatus());
            List<PlanDesignShareRecord> shareRecordList = shareService.findPlanShareRecordList(planDesignShareRecord);
            if (CollectionUtils.isEmpty(shareRecordList)) {
                if (Objects.equals(plan.getStatus(), PlanStatusEnum.published.name())) {
                    String businessKey = plan.getBusinessKey();
                    PlanDesignInstanceDTO assetsLatestPlan = planDesignInstanceService.getAssetsLatestPlan(businessKey, null);
                    if (assetsLatestPlan != null && assetsLatestPlan.getId() != null) {
                        return new ResultMsg(planDesignInstanceService.getById(assetsLatestPlan.getId()));
                    } else {
                        return new ResultMsg(planDesignInstanceService.getById(id));
                    }
                } else {
                    return new ResultMsg(false, 404, "暂无权限");
                }
            }
        }
        return new ResultMsg(planDesignInstanceService.getById(id));
    }

    /**
     * 根据id删除
     */
    @DeleteMapping("{id}")
    public ResultMsg deleteById(@PathVariable Long id) {
        planDesignInstanceService.deleteToRecycleBin(id);
        return ResultMsg.ok();
    }

    /**
     * 列表分页查询
     */
    @PostMapping("list")
    public ResultMsg list(@RequestBody @Valid PlanDesignInstanceQueryRequest request) {
        SysUser sysUser = SysUtil.getCurrentUserInfo();
        Page<PlanDesignInstance> page = planDesignInstanceService.list(request, sysUser);
        if (page.getTotalRows() > 0) {
            for (PlanDesignInstance planDesignInstance : page.getData()) {
                String status = planDesignInstance.getStatus();
                status = PlanStatusEnum.queryShowName(status);
                planDesignInstance.setStatus(status);
            }
        }
        return new ResultMsg(page);
    }

    /**
     * 交付物分享接口
     */
    @PostMapping("/addOrUpdateShareRecord")
    public ResultMsg addOrUpdateShareRecord(@RequestBody PlanDesignShareRecord planDesignShareRecord) {
        Assert.isTrue(planDesignShareRecord.getSharedLoginCode() != null, "被分享的人code不能为空");
        Assert.isTrue(planDesignShareRecord.getPlanDesignId() != null, "分享的交付物不能为空");
        Assert.isTrue(planDesignShareRecord.getPermission() != null, "分享的权限不能为空");
        PlanSharePermissionEnum permission =
                PlanSharePermissionEnum.getPermission(planDesignShareRecord.getPermission());
        Assert.isTrue(permission != null, "分享的权限不存在");
        Long result = planDesignInstanceService.addOrUpdateShareRecord(planDesignShareRecord);
        if (Objects.equals(result, -1L)){
            return new ResultMsg(false, 404, "暂无权限!");
        } else {
            return new ResultMsg(result);
        }
    }

    /**
     * 交付物取消分享接口
     */
    @PostMapping("/cancelShareRecord")
    public ResultMsg cancelShareRecord(@RequestBody PlanDesignShareRecord planDesignShareRecord) {
        Assert.isTrue(planDesignShareRecord.getId() != null, "分享的id不能为空");
        planDesignInstanceService.cancelShareRecord(planDesignShareRecord);
        return ResultMsg.ok();
    }

    /**
     * 查询与我协作的交付物
     */
    @PostMapping("/getMyCoopPlanDesign")
    public void getMyCoopPlanDesign(HttpServletRequest request, HttpServletResponse response,
                                    @RequestBody PlanDesignInstanceQueryRequest planDesignInstanceQueryRequest) {
        Page<PlanDesignInstance> result = planDesignInstanceService.getMyCoopPlanDesign(planDesignInstanceQueryRequest);
        ControllerUtils.returnJson(request, response, result);
    }

    /**
     * 查询已发布模板下面的类型list
     */
    @GetMapping("/getReleaseTemplateType")
    public void getReleaseTemplateType(HttpServletRequest request, HttpServletResponse response) {
        List<TemplateType> result = planDesignInstanceService.getReleaseTemplateType();
        ControllerUtils.returnJson(request, response, result);
    }

    /**
     * 复制方案设计
     *
     * @param request
     * @param response
     * @param planId
     */
    @GetMapping("/copyPlanInfoById") public void copyPlanInfoById(HttpServletRequest request, HttpServletResponse response, @RequestParam Long planId,@RequestParam(name="planName",required = false) String planName) {
        if (planName!=null && planName.length() > 50) {
            throw new BusinessException("方案名称过长,修改方案名称完成复制",planName);
        }
        Boolean result = planDesignInstanceService.copyPlanInfoById(planId,planName);
        ControllerUtils.returnJson(request, response, result);
    }

    /**
     * 方案预览
     */
    @GetMapping("preview")
    public ResultMsg planPreview(Long planId) {
        PlanPreviewVO vo = planChapterInstanceService.planPreview(planId);
        return new ResultMsg(vo);
    }

    @GetMapping("/updatePlanDiagramIsFlow")
    public ResultMsg updatePlanDiagramIsFlow(@RequestParam("planId") Long planId, @RequestParam("status") Integer status) {
        Boolean result = planDesignInstanceService.updatePlanDiagramIsFlow(planId, status);
        return new ResultMsg(result);
    }

    @GetMapping("/checkPlan")
    public ResultMsg checkPlan(@RequestParam("planId") Long planId) {
        Map<String, Object> result = planDesignInstanceService.checkPlan(planId);
        if (Boolean.TRUE.equals(result.get("result"))
                && Boolean.FALSE.equals(result.get("assertDirExist"))) {
            return new ResultMsg(Boolean.TRUE, ResultCodeEnum.DELETE_ASSETS_DIR_ERROR.getCode(), ResultCodeEnum.DELETE_ASSETS_DIR_ERROR.getMessage());
        }
        return new ResultMsg(result);
    }

    @PostMapping("/batchCheckPlan")
    public ResultMsg batchCheckPlan(@RequestBody List<Long> planIdList) {
        Map<String, Object> result = planDesignInstanceService.batchCheckPlan(planIdList);
        return new ResultMsg(result);
    }

    /**
     * 方案提交审批
     *
     * @return
     */
    @PostMapping("/submitApproval")
    public ResultMsg submitApproval(@RequestBody ProcessApprovalRequest request) {
        if (request.getPlanId() == null) {
            throw new BusinessException("方案主键不能为空!");
        }
        SysUser user = SysUtil.getCurrentUserInfo();
        PlanDesignInstance plan = planDesignInstanceDao.getById(request.getPlanId());
        if (plan == null) {
            throw new BusinessException("获取方案信息错误!");
        }
        Long result = planDesignInstanceService.submitApproval(user, request, plan);
        if (Objects.equals(result, -1L)) {
            return new ResultMsg(Boolean.TRUE, ResultCodeEnum.APPROVE_ERROR.getCode(), "方案【" + plan.getName() + "】已提交审批，请勿重复提交");
        } else if (Objects.equals(result, -2L)) {
            return new ResultMsg(Boolean.TRUE, ResultCodeEnum.DELETE_ASSETS_DIR_ERROR.getCode(), ResultCodeEnum.DELETE_ASSETS_DIR_ERROR.getMessage());
        } else if (Objects.equals(result, -3L)) {
            return new ResultMsg(Boolean.TRUE, ResultCodeEnum.REPEAT_OPERATE.getCode(), ResultCodeEnum.REPEAT_OPERATE.getMessage());
        } else if (Objects.equals(result, -4L)) {
            return new ResultMsg(Boolean.TRUE, ResultCodeEnum.TASK_FAILURE.getCode(), ResultCodeEnum.TASK_FAILURE.getMessage());
        } else {
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("result", true);
            return new ResultMsg(resultMap);
        }

    }

    /**
     * 供性能测试使用，批量发布方案
     * @param planIdList
     * @return
     */
    @PostMapping("/batchPublishPlan")
    public ResultMsg batchPublishPlan(@RequestBody List<Long> planIdList) {
        planDesignInstanceService.batchPublishPlan(planIdList);
        return ResultMsg.ok();
    }

    /**
     * 供性能测试使用，修改方案关联系统
     * @param dirId
     * @return
     */
    @GetMapping("/updatePlanRelationSys")
    public ResultMsg updatePlanRelationSys(@RequestParam Long dirId) {
        List<Long> planIds = planDesignInstanceService.updatePlanRelationSys(dirId);
        return new ResultMsg(planIds);
    }

    @GetMapping("/getSystemList")
    public ResultMsg getSystemList(Long classId, @RequestParam("libType") LibType libType) {
        Object obj = planDesignInstanceService.getSystemList(classId, libType);
        return new ResultMsg(obj);
    }

    @GetMapping("/deletePublishedPlan")
    public ResultMsg deletePublishedPlan(@RequestParam Long planId) {
        //入参校验
        if (planId == null) {
            throw new BusinessException("删除发布的方案id不能为空");
        }
        Boolean result = planDesignInstanceService.deletePublishedPlan(planId);
        return new ResultMsg(result);
    }

    /**
     * TODO 只做清洗数据使用
     * @param dirType
     * @return
     */
    @GetMapping("/updatePlanDirType")
    public ResultMsg updatePlanDirType(@RequestParam("dirType") Integer dirType) {
        boolean result = planDesignInstanceService.updatePlanDirType(dirType);
        return new ResultMsg(result);
    }

    @GetMapping("/downLoadAllFile")
    public ResponseEntity<byte[]> downLoadAllFile(@RequestParam("planId") Long planId) {
        return planDesignInstanceService.downLoadAllFile(planId);
    }

    @GetMapping("/findAllPlanListForFeign")
    public List<PlanDesignInstanceDTO> findAllPlanListForFeign(@RequestParam("dirId") Long dirId, @RequestParam("dirType") Integer dirType,
                                                               @RequestParam(value = "name", required = false) String name,
                                                               @RequestParam(value = "publishStatus", required = false)Integer publishStatus) {
        return planDesignInstanceService.findAllPlanListForFeign(dirId, dirType, name, publishStatus);
    }

    /**
     * 获取方案列表
     * @param pageNum 页码
     * @param pageSize 每页数量
     * @param diagramId 视图id
     * @param type 0：设计库视图 1：资产库视图
     * @return
     */
    @GetMapping("/findDiagramPlanList")
    public ResultMsg findDiagramPlanList(@RequestParam(name = "pageNum", defaultValue = "1") Integer pageNum,
                                         @RequestParam(name = "pageSize", defaultValue = "20") Integer pageSize,
                                         @RequestParam(name = "diagramId") String diagramId,
                                         @RequestParam(name = "type") Integer type) {
        Page<PlanInfoVO> planList = planDesignInstanceService.findDiagramPlanList(pageNum, pageSize, diagramId, type);
        return new ResultMsg(planList);
    }

    @GetMapping("/getPlanForFeign")
    public PlanDesignInstanceDTO getPlanForFeign(@RequestParam("planId") Long planId) {
        PlanDesignInstance planDesignInstance = planDesignInstanceService.getPlanDesignInstance(planId);
        if (planDesignInstance != null) {
            PlanDesignInstanceDTO planDesignInstanceDTO = new PlanDesignInstanceDTO();
            BeanUtils.copyProperties(planDesignInstance, planDesignInstanceDTO);
            return planDesignInstanceDTO;
        }
        return null;
    }

    @PostMapping("/getPlanBatchForFeign")
    public List<PlanDesignInstanceDTO> getByIds(@RequestBody Collection<Long> ids) {
        List<PlanDesignInstance> planDesignInstances = planDesignInstanceService.getByIds(ids);
        if (CollectionUtils.isEmpty(planDesignInstances)) {
            return new ArrayList<>();
        }
        List<PlanDesignInstanceDTO> results = new ArrayList<>();
        PlanDesignInstanceDTO planDesignInstanceDTO;
        for (PlanDesignInstance instance : planDesignInstances) {
            planDesignInstanceDTO = new PlanDesignInstanceDTO();
            BeanUtils.copyProperties(instance, planDesignInstanceDTO);
            results.add(planDesignInstanceDTO);
        }
        return results;
    }

    /**
     * 检出方案
     * @return
     */
    @PostMapping("/detectionPlan")
    public ResultMsg detectionPlan(@RequestBody DetectionPlanVo detectionPlanVo) {
        SysUser sysUser = SysUtil.getCurrentUserInfo();
        if (sysUser == null || StringUtils.isEmpty(sysUser.getLoginCode())) {
            throw new BusinessException("获取用户错误!");
        }
        JSONObject result = planDesignInstanceService.detectionPlan(detectionPlanVo, sysUser);
        return new ResultMsg(result);
    }

    /**
     * 方案历史版本
     *
     * @param planId
     * @return
     */
    @GetMapping("/findPlanHistoryVersionList")
    public ResultMsg findPlanHistoryVersionList(HttpServletResponse response, @RequestParam("planId") Long planId) {
        List<PlanHistoryVersionVo> result = planDesignInstanceService.findPlanHistoryVersionList(planId);
        return new ResultMsg(result);
    }

    /**
     * 查询方案最新版本
     *
     * @param planId
     * @return
     */
    @GetMapping("/getPlanLatestVersion")
    public ResultMsg getPlanLatestVersion(@RequestParam("planId") Long planId, @RequestParam("type") Integer type) {
        PlanHistoryVersionVo planHistoryVersionVo = planDesignInstanceService.getPlanLatestVersion(planId, type);
        return new ResultMsg(planHistoryVersionVo);
    }

    @GetMapping("/findRenewVersionPlanList")
    public List<PlanDesignInstanceDTO> findRenewVersionPlanList(@RequestParam("planId") Long planId) {
        return planDesignInstanceService.findRenewVersionPlanList(planId);
    }

    @PostMapping("/findDesignHistoryPlanList")
    public List<PlanDesignInstanceDTO> findDesignHistoryPlanList(@RequestBody List<Long> historyPlanIds) {
        return planDesignInstanceService.findDesignHistoryPlanList(historyPlanIds);
    }

    @GetMapping("/getAssetsLatestPlan")
    public PlanDesignInstanceDTO getAssetsLatestPlan(@RequestParam("businessKey") String businessKey, @RequestParam("dirType") Integer dirType) {
        return planDesignInstanceService.getAssetsLatestPlan(businessKey, dirType);
    }

    @PostMapping("/findAssetsLatestPlanList")
    public List<PlanDesignInstanceDTO> findAssetsLatestPlanList(@RequestBody List<PlanVersionDTO> planVersionList) {
        return planDesignInstanceService.findAssetsLatestPlanList(planVersionList);
    }

    @GetMapping("/findShareRecordList")
    public List<PlanDesignShareRecordDTO> findShareRecordList(@RequestParam("planId") Long planId) {
        return planDesignInstanceService.findShareRecordList(planId);
    }

    @GetMapping("/findByTemplateId")
    public List<PlanDesignInstanceDTO> findByTemplateId(@RequestParam("templateId") Long templateId) {
        return planDesignInstanceService.findByTemplateId(templateId);
    }

    @GetMapping("/exportPlan")
    public ResultMsg exportPlan(HttpServletResponse response, @RequestParam("planId") Long planId) {
        String path = planDesignInstanceService.exportPlan(response, planId);
        return new ResultMsg(path);
    }
    @PostMapping("/exportPlan2")
    public ResultMsg exportPlan2(HttpServletResponse response, @RequestBody ExportPlanVo exportPlanVo) {
        String path = planDesignInstanceService.exportPlan2(response, exportPlanVo);
        return new ResultMsg(path);
    }
    @GetMapping("findPublishedPlanDesignList")
    public RemoteResult findPublishedPlanDesignList(@RequestParam("name") String name) {
        return new RemoteResult(planDesignInstanceService.findPublishedPlanDesignList(name));
    }

    /**
     * 新网改版开启流程审批
     * @param businessKey
     * @return
     */
    @GetMapping("/checkQuestion")
    public ResultMsg checkQuestion(@RequestParam String businessKey) {
        planDesignInstanceService.checkQuestion(businessKey);
        return new ResultMsg();
    }

    /**
     * 新网改版校验发布位置
     * @param businessKey
     * @return
     */
    @GetMapping("/checkPublishAssetsDir")
    public ResultMsg checkPublishAssetsDir(@RequestParam String businessKey) {
        Long result = planDesignInstanceService.checkPublishAssetsDir(businessKey);
        if (result != null && Objects.equals(result, -2L)) {
            return new ResultMsg(false, ResultCodeEnum.DELETE_ASSETS_DIR_ERROR.getCode());
        }
        return ResultMsg.ok();
    }
}

